[Spring-6] SpringWeb Body Data 처리(ResponseBody)
📦

[Spring-6] SpringWeb Body Data 처리(ResponseBody)

Lecture
Framework
태그
dev
spring
public
완성
Y
생성일
Mar 17, 2024 01:04 PM
LectureName
Spring

파라미터가 아닌 HTTP Body에 실려오는 정보들 어떻게 처리할까?

GET, POST 뿐만이 아니라 파라미터(age=123) 형식이 아닌 Body데이터 자체를 넘기는 것에 대한 내용이다. text 뿐만이 아니라 Rest API에서 사용하는 Json 형식 또한 다뤄볼 것이다.
 
💡
알아야 하는 지식
Pojo
코드에서 설명 예정
@ResponseBody
말 그대로 Body데이터를 직접 처리하는 것을 말합니다. 해당 어노테이션을 사용하면 spring은 리턴 코드 섹션에서 뷰 템플릿을 찾기 않고 바로 body값을 사용자에게 리턴합니다.
 

1. 단순 텍스트 처리

💡
예~~~~~~~~~~~전 올드한 코드부터 진보해가는 과정을 설명드릴겁니다.
 
 
기본(올드)
첫번째로, HttpServletRequest 객체를 이용하여 InputStream으로부터 데이터를 읽어와 처리하는 방법을 설명합니다.
@PostMapping("/req-body1") @Responsebody public void requestBodyString1(HttpServletRequest req, HttpServletResponse res) throws IOException{ ServletInputStream inputStream = req.getInputStream(); String msgBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8); //스트림은 항상 바이트코드이다. log.info("messageBody={}", msgBody); res.getWriter().write("클라이언트에게 전송합니다."); }
  • InputStream 은 바이트코드를 읽어내는 클래스 입니다. 바이트 코드 자체로는 문장을 해석할 수 없기 때문에 표준 규약인 UTF-8로 인코딩 하는 것이 바람직합니다.
 
 
발전 1
두번째로는 InputStreamWriter 매개변수를 이용하여 HTTP Body의 데이터를 처리하는 방법을 설명합니다.
@PostMapping("/req-body2") @Responsebody public void requestBodyString2(InputStream inputStream, Writer resWriter) throws IOException{ //매개변수로 바로 받을 수 있다. String msgBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8); log.info("messageBody={}",msgBody); resWriter.write("클라이언트에게 해당 데이터를 전송합니다."); }
  • 해당 코드에서 InputStream은 HTTP 요청의 Body 데이터를 바이트 단위로 읽어 들이는 역할을 합니다. StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8) 을 통해 바이트 코드를 문자열로 변환하여 msgBody 변수에 저장합니다.
 
 
발전 2
@PostMapping("/req-body3") @Responsebody public HttpEntity<String> requestBodyString3(HttpEntity<String> httpEntity) throws IOException{ //http message converter //Http 엔티티를 제공한다. Http 헤더, body정보를 정말 편리하게 조회한다. // 응답 또한 사용 가능하다. String msgBody = httpEntity.getBody(); log.info("messageBody={}", msgBody); return new HttpEntity<>("body 메세지를 여기다가 넣습니다."); //http status 또한 응답할 수 있음 }
  • HttpEntity는 Spring에서 HTTP 요청 및 응답을 처리하는 클래스입니다. HTTP 요청의 Body 데이터를 조회하거나, HTTP 응답을 생성할 때 사용할 수 있습니다. HttpEntity는 HTTP Body를 포함하는 객체로, getBody() 메소드를 통해 HTTP Body 정보를 조회할 수 있습니다.
  • HttpEntity<객체> 에서 객체에 들어갈 타입으론 String, Integer등이 가능합니다. 객체 형태만 가능하기 때문에 int등 타입을 쓰지 않도록 조심해야 합니다.
 
 
최종
마지막으로, @RequestBody 어노테이션을 사용하여 간단하게 HTTP Body의 데이터를 처리하는 방법을 설명합니다.
//많이 씀 @PostMapping("/req-body4") @Responsebody public String requestBodyString4(@RequestBody String msgBody) throws IOException{ //@RequestBody를 통한 간편화 log.info("messageBody={}", msgBody); return "ok"; }
  • 사실 그냥 이거 쓰면 됩니다
 
 
 

2. JSON 데이터 처리

JSON 데이터 같은 경우에는 REST API 형식으로 개발 시 많이 사용하는 데이터 타입입니다. JSON 데이터를 다루는 법 또한 알아보겠습니다.
 
 
기본
ObjectMapper는 Jackson 라이브러리에서 제공하는 클래스로, JSON 데이터를 Java Object로 변환할 때 사용합니다.
POJO란 Plain Old Java Object의 약어로, Java 객체를 표현하는 표준적인 방법입니다. POJO 객체는 따로 상속 받거나 구현할 필요가 없으며, Java Bean 규약을 따르기만 하면 됩니다.
위 코드에서 ObjectMapper는 JSON 데이터를 Student 객체로 변환하기 위해 사용됩니다. Student 객체는 POJO 객체입니다.
private ObjectMapper objectMapper = new ObjectMapper(); @PostMapping("/req-body-json1") @ResponseBody public void requestBodyJson1(HttpServletRequest req, HttpServletResponse res) throws IOException { ServletInputStream inputStream = req.getInputStream(); String msgBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8); log.info("msgBody={}", msgBody); Student student = objectMapper.readValue(msgBody, Student.class); log.info("username={}, age={}", student.getName(), student.getAge()); res.getWriter().write("ok"); }
 
 
발전 1
@ResponseBody @PostMapping("/req-body-json2") public String requestBodyJson2(@RequestBody String msgBody) throws IOException { log.info("msgBody={}", msgBody); Student student = objectMapper.readValue(msgBody, Student.class); //student 객체가 생성 log.info("username={}, age={}", student.getName(), student.getAge()); return "ok"; }
  • @RequestBody를 이용해서 body값을 가져온 후 매핑합니다.
 
 
발전 2
@ResponseBody @PostMapping("/req-body-json3") public String requestBodyJson3(HttpEntity<Student> student) { Student data = student.getBody(); log.info("username={}, age={}", data.getName(), data.getAge()); return "ok"; } //@RequestBody를 생략하면 ModelAttribute로 처리된다.
  • HttpEntity를 사용해서 Student로 바로 Object를 매핑하면 따로 ObjectMapper을 사용할 필요가 없다.
 
 
발전 2 +
@ResponseBody @PostMapping("/req-body-json5") //json -> 객체 -> json public Student requestBodyJson5(HttpEntity<Student> student) { Student data = student.getBody(); log.info("username={}, age={}", data.getName(), data.getAge()); return data; } //@RequestBody를 생략하면 ModelAttribute로 처리된다.
  • 다시 json 형태로 data를 보낼수도 있다.
 
 
발전 2 ++
@ResponseBody @PostMapping("/req-body-json4") public String requestBodyJson4(@RequestBody Student student) { log.info("username={}, age={}", student.getName(), student.getAge()); return "ok"; }
  • 바로 Pojo 객체 타입으로 선언해서 사용도 가능하다.
  • 추후에 DTO를 이용하여 파라미터를 설정할 수 있는데, 이때 DTO 객체를 반환하게 되면 발전 이전의 코드를 작성할 필요가 없습니다.
  • 여기서 Student DTO(클래스) 를 반환하게 되면 자동으로 JSON 데이터가 반환됩니다.
 

3. @ResponseBody와 HttpEntity는 각각 언제 쓰면 될까?

@ResponseBody 어노테이션은 컨트롤러 메소드에서 리턴되는 객체를 HTTP 응답으로 전송하기 위해 사용됩니다. 객체는 자동으로 JSON 형식으로 변환됩니다.
 
반면 HttpEntity는 요청 또는 응답의 HTTP 헤더와 바디를 포함하는 클래스입니다. @RequestBody 어노테이션과 함께 사용하여 요청 본문을 객체로 변환하거나, 응답 본문을 객체로 만들어 HTTP 응답을 생성할 수 있습니다.
 
즉, @ResponseBody는 컨트롤러 메소드의 리턴 타입이 객체일 때 사용하고, HttpEntity는 요청 및 응답의 HTTP 헤더와 바디를 직접 다룰 때 사용합니다.
 
또한 HttpEntity의 경우 HttpStatus를 보낼 수 있는 차이 또한 있습니다.
 
💡
그래서 등장한 @RestController
  • 클래스 단에서 @Controller 대신 @RestController을 사용하면 코드 모든 곳에 @ResponseBody어노테이션이 적용됩니다.